﻿using System;
using System.Text;

namespace FRAFV.Common
{
	/// <summary xml:lang="ru">
	/// Предоставляет набор методов типа <see langword="static"/> для удобства использования
	/// строк <see cref="T:System.String"/>.
	/// </summary>
	public static class StringExtensions
	{
		#region Empty string extensions
		/// <summary xml:lang="ru">
		/// Указывает, является ли заданная строка <see cref="T:System.String"/> значением <see langword="null"/>
		/// или пустой строкой (<c>""</c>).
		/// </summary>
		/// <summary xml:lang="en">
		/// Indicates whether a specified string is <see langword="null"/> or empty.
		/// </summary>
		/// <param name="self" xml:lang="en">The string to test.</param>
		/// <param name="self" xml:lang="ru">Строка для проверки.</param>
		/// <returns xml:lang="ru"><see langword="true"/>, если параметр <paramref name="value"/>
		/// равен <see langword="null"/> или пустой строке (<c>""</c>); в противном случае — <see langword="false"/>.</returns>
		/// <returns xml:lang="en"><see langword="true"/> if the <paramref name="value"/>
		/// parameter is <see langword="null"/> or empty.</returns>
		/// <seealso cref="M:System.String.IsNullOrEmpty(System.String)"/>
		public static bool IsNullEmpty(this string self)
		{
			return String.IsNullOrEmpty(self);
		}

		/// <summary xml:lang="ru">
		/// Указывает, является ли заданная строка <see cref="T:System.String"/> значением <see langword="null"/>,
		/// пустой строкой (<c>""</c>) или строкой, состоящей только из пробельных символов.
		/// </summary>
		/// <summary xml:lang="en">
		/// Indicates whether a specified string is <see langword="null"/>, empty, or consists only of white-space characters.
		/// </summary>
		/// <param name="self" xml:lang="en">The string to test.</param>
		/// <param name="self" xml:lang="ru">Строка для проверки.</param>
		/// <returns xml:lang="ru"><see langword="true"/>, если параметр <paramref name="value"/>
		/// равен <see langword="null"/>, пустой строке (<c>""</c>) либо если параметр <paramref name="value"/>
		/// содержит только пробельные символы; в противном случае — <see langword="false"/>.</returns>
		/// <returns xml:lang="en"><see langword="true"/> if the <paramref name="value"/>
		/// parameter is <see langword="null"/> or empty, or if <paramref name="value"/>
		/// consists exclusively of white-space characters.</returns>
		/// <seealso cref="M:System.String.IsNullOrWhiteSpace(System.String)"/>
		public static bool IsNullSpace(this string self)
		{
			return String.IsNullOrWhiteSpace(self);
		}

		/// <summary xml:lang="ru">
		/// Всегда возвращает строку <see cref="T:System.String"/>.
		/// </summary>
		/// <summary xml:lang="en">
		/// Get not null string
		/// </summary>
		/// <param name="self" xml:lang="en">String or null.</param>
		/// <param name="self" xml:lang="ru">Строка либо <see langword="null"/>.</param>
		/// <returns xml:lang="ru">Исходная строка <paramref name="self"/>, если она не равна <see langword="null"/>;
		/// в противном случае — пустая строка (<c>""</c>).</returns>
		/// <returns xml:lang="en">String or empty string.</returns>
		public static string EmptyIfNull(this string self)
		{
			return self ?? String.Empty;
		}

		/// <summary xml:lang="ru">
		/// Возвращает непустую строку <see cref="T:System.String"/>.
		/// </summary>
		/// <summary xml:lang="en">
		/// Get not empty string.
		/// </summary>
		/// <param name="self" xml:lang="en">String or null.</param>
		/// <param name="self" xml:lang="ru">Строка либо <see langword="null"/>.</param>
		/// <returns xml:lang="ru">Исходная строка <paramref name="self"/>, если она не равна
		/// пустой строке (<c>""</c>); в противном случае — значение <see langword="null"/>.</returns>
		/// <returns xml:lang="en">Not empty string or <see langword="null"/>.</returns>
		public static string NullIfEmpty(this string self)
		{
			return self == String.Empty ? null : self;
		}

		public static string NullIfSpace(this string self)
		{
			return String.IsNullOrWhiteSpace(self) ? null : self;
		}
		#endregion

		#region Substring extensions
		/// <summary xml:lang="ru">
		/// Возвращает левую (начальную) часть строки <see cref="T:System.String"/>.
		/// Подстрока имеет указанную длину.
		/// </summary>
		/// <summary xml:lang="en">
		/// Get left part of the string.
		/// </summary>
		/// <param name="self" xml:lang="en">String.</param>
		/// <param name="self" xml:lang="ru">Строка.</param>
		/// <param name="len" xml:lang="en">Number of characters to get from begin.</param>
		/// <param name="len" xml:lang="ru">Число символов в подстроке.</param>
		/// <returns xml:lang="ru">
		/// <para>Объект <see cref="T:System.String"/>, эквивалентный подстроке длиной
		/// не более чем <paramref name="length"/>, которая начинается в начале строки <paramref name="self"/>,</para>
		/// <para>— или —</para>
		/// <para>Пустая строка (<c>""</c>), если значение <paramref name="length"/> равно нулю
		/// либо строка <paramref name="self"/> пустая (<see langword="null"/>).</para>
		/// </returns>
		/// <returns xml:lang="en">First len characters.</returns>
		/// <seealso cref="M:System.String.Substring(System.Int32,System.Int32)"/>
		public static string Left(this string self, int len)
		{
			if (IsNullEmpty(self))
				return String.Empty;
			if (len >= self.Length)
				return self;
			return self.Substring(0, len);
		}

		/// <summary xml:lang="ru">
		/// Возвращает правую (конечную) часть строки <see cref="T:System.String"/>.
		/// Подстрока имеет указанную длину.
		/// </summary>
		/// <summary xml:lang="en">
		/// Get right part of the string
		/// </summary>
		/// <param name="self" xml:lang="en">String.</param>
		/// <param name="self" xml:lang="ru">Строка.</param>
		/// <param name="len" xml:lang="en">Number of characters to get from end.</param>
		/// <param name="len" xml:lang="ru">Число символов в подстроке.</param>
		/// <returns xml:lang="ru">
		/// <para>Объект <see cref="T:System.String"/>, эквивалентный подстроке длиной
		/// не более чем <paramref name="length"/>, которая заканчивается в конце строки <paramref name="self"/>,</para>
		/// <para>— или —</para>
		/// <para>Пустая строка (<c>""</c>), если значение <paramref name="length"/> равно нулю
		/// либо строка <paramref name="self"/> пустая (<see langword="null"/>).</para>
		/// </returns>
		/// <returns xml:lang="en">Last len characters.</returns>
		/// <seealso cref="M:System.String.Substring(System.Int32,System.Int32)"/>
		public static string Right(this string self, int len)
		{
			if (IsNullEmpty(self))
				return String.Empty;
			if (len >= self.Length)
				return self;
			return self.Substring(self.Length - len);
		}

		/// <summary xml:lang="ru">
		/// Возвращает подстроку строки <see cref="T:System.String"/>, которая следует
		/// за первым вхождением разделителя, или пустую строку, если строка не содержит
		/// разделитель.
		/// </summary>
		/// <summary xml:lang="en">
		/// Returns the substring that follows the first occurrence of the separator
		/// string in the string, or the empty string if the string does not contain
		/// the separator string.
		/// </summary>
		/// <param name="self" xml:lang="en">String.</param>
		/// <param name="self" xml:lang="ru">Строка.</param>
		/// <param name="after" xml:lang="en">Separator.</param>
		/// <param name="after" xml:lang="ru">Разделитель.</param>
		/// <returns xml:lang="ru">
		/// Возвращает подстроку строки <see cref="T:System.String"/>, которая следует
		/// за первым вхождением разделителя <paramref name="after"/>, или пустую строку,
		/// если строка не содержит разделитель <paramref name="after"/>.
		/// </returns>
		/// <returns xml:lang="en">
		/// Returns the substring that follows the first occurrence of <paramref name="after"/>
		/// string in the string, or the empty string if the string does not contain
		/// <paramref name="after"/> string.
		/// </returns>
		/// <remarks xml:lang="ru">
		/// Эта функция учитывает регистр символов.
		/// </remarks>
		/// <remarks xml:lang="en">
		/// This function is case-sensitive.
		/// </remarks>
		/// <seealso cref="M:System.String.Substring(System.Int32,System.Int32)"/>
		public static string SubstringAfter(this string self, string after)
		{
			if (IsNullEmpty(self) || IsNullEmpty(after))
				return string.Empty;
			int k = self.IndexOf(after);
			if (k < 0)
				return string.Empty;
			else
				return self.Substring(k + after.Length);
		}

		/// <summary xml:lang="ru">
		/// Возвращает подстроку строки <see cref="T:System.String"/>, стоящей до первого
		/// вхождения разделителя. Если разделитель не вложен в строку, то возвращается
		/// пустая строка.
		/// </summary>
		/// <summary xml:lang="en">
		/// Returns the substring that precedes the first occurrence of the separator
		/// string in the string, or the empty string if the string does not contain 
		/// the separator string.
		/// </summary>
		/// <param name="self" xml:lang="en">String.</param>
		/// <param name="self" xml:lang="ru">Строка.</param>
		/// <param name="after" xml:lang="en">Separator.</param>
		/// <param name="after" xml:lang="ru">Разделитель.</param>
		/// <returns xml:lang="ru">
		/// Возвращает подстроку строки <see cref="T:System.String"/>, стоящей до первого
		/// вхождения разделителя <paramref name="before"/>. Если разделитель <paramref name="before"/>
		/// не вложен в строку, то возвращается пустая строка.
		/// </returns>
		/// <returns xml:lang="en">
		/// Returns the substring that precedes the first occurrence of <paramref name="before"/>
		/// string in the string, or the empty string if the string does not contain 
		/// <paramref name="before"/> string.
		/// </returns>
		/// <remarks xml:lang="ru">
		/// Эта функция учитывает регистр символов.
		/// </remarks>
		/// <remarks xml:lang="en">
		/// This function is case-sensitive.
		/// </remarks>
		/// <seealso cref="M:System.String.Substring(System.Int32,System.Int32)"/>
		public static string SubstringBefore(this string self, string before)
		{
			if (IsNullEmpty(self) || IsNullEmpty(before))
				return string.Empty;
			int k = self.IndexOf(before);
			if (k < 0)
				return string.Empty;
			else
				return self.Substring(0, k);
		}
		#endregion
	}
}
